




# 获取哔哩哔哩直播的真实流媒体地址，默认获取直播间提供的最高画质
# qn=150高清
# qn=250超清
# qn=400蓝光
# qn=10000原画
# 获取方法参考：https://blog.csdn.net/zy1281539626/article/details/112451021

import requests
import json
import time


url_keys=("http_hls_fmp4_avc","http_hls_ts_avc","http_stream_flv_avc")
ua="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36"

f_url = 'https://api.live.bilibili.com/xlive/web-room/v2/index/getRoomPlayInfo'

class BiliBili:

    NAME="BILIBILI"
    def __init__(self, room_id):
        self.rid = room_id
        self.timeout=(15,15)
        self.header = {
            'User-Agent': ua
        }

    def get_real_url(self):
        # 先获取直播状态和真实房间号
        r_url = 'https://api.live.bilibili.com/room/v1/Room/room_init?id={}'.format(self.rid)

        with requests.Session() as session:
            # 这步 很耗时!!!? timeout(connect,read)
            # 受这个 这个connect 影响, 之前的 openwrt N1  connect=15 都没事
            # rk3399 中 connect=15 用时15秒 , connect=2 用时2.5秒
            # 所以只能设短一些.  !!
            # session 中都是 keepAlive的 所以第一个 get()的connect耗时!!
            t0=time.time()
            res = session.get(r_url, headers=self.header)#, timeout=self.timeout)
            print("[info] =====>time used1:", round(time.time()-t0,4))

            # print(res)
            # print(self.header)
            # print(res.headers)

            res=res.json()
            code = res['code']
            if code == 0:
                live_status = res['data']['live_status']
                if live_status == 1:
                    room_id = res['data']['room_id']

                    urls = {}
                    params = {
                        'room_id': room_id,
                        'no_playurl': 0,
                        'mask': 0,
                        'qn': 10000,
                        'platform': 'web',
                        'protocol': '0,1',  # http_stream: 0, http_hls: 1
                        'format': '0,1,2',  # flv: 0, ts: 1, fmp4: 2
                        'codec': '0,1'      # avc: 0, hevc: 1
                    }

                    resp = session.get(f_url, params=params, headers=self.header, timeout=self.timeout)
                    resp=resp.json()

                    try:
                        streams = resp['data']['playurl_info']['playurl']['stream']
                        for stream in streams:
                            protocol_name = stream['protocol_name']
                            for format in stream['format']:
                                format_name = format['format_name']
                                for codec in format['codec']:
                                    codec_name = codec['codec_name']
                                    for url_info in codec['url_info']:
                                        urls[protocol_name + '_' + format_name + '_' + codec_name] \
                                        = url_info['host'] + codec['base_url'] + url_info['extra']
                        return {k: urls[k] for k in sorted(urls.keys())}
                    except KeyError or IndexError:
                        raise Exception('获取失败')

                else:
                    raise Exception('未开播')
            else:
                raise Exception('房间不存在')

    # 其他 两个 可以 一个是视频, 一个是音频
    ##  video: "http_hls_ts_avc"
    ##  audio: "http_stream_flv_avc"
    def check_url(self,u):
        try:
            if u is None:
                return False
            if u.startswith("http"):
                return True
        except Exception as e:
            pass
        return False


    def get_live_url(self):
        for k in url_keys:
            print("key:",k)
            x=self.get_real_url().get(k)
            if self.check_url(x):
                return x,0
        return "",0


def get_real_url(rid,key=None):
    try:
        bilibili = BiliBili(rid)
        if key is None:
            return bilibili.get_real_url()
        if bilibili.get(key) is None:
            return None
        return bilibili.get(key)
    except Exception as e:
        print('Exception：', e)
        return None


if __name__ == '__main__':
    r = input('请输入bilibili直播房间号：\n')
    if r=='test':
        r="833792"
    print("room id={};".format(r))
    print(json.dumps(get_real_url(r), indent=4))


